package com.donger.auth;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.donger.common.core.constant.CommonConstants;
import com.donger.common.core.constant.SecurityConstants;
import com.donger.common.security.service.BootUserDetailsService;
import com.donger.common.security.service.UserDetail;
import com.donger.upms.api.entity.SysRole;
import com.donger.upms.api.entity.SysUser;
import com.donger.upms.api.service.ISysRoleService;
import com.donger.upms.api.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 实现 自定义认证 实现 BootUserDetailsService 继承的 UserDetailsService 类中 loadUserByUsername方法即可
 * <p>
 * 返回值 UserDetails 为 Spring Security提供的 可以自己另行实现
 * <p>
 * 用户认证service
 *
 * @author xyx
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserDetailsServiceImpl implements BootUserDetailsService {

    private final ISysUserService sysUserService;

    private final ISysRoleService sysRoleService;

    /**
     * 用户名密码登陆
     * <p>
     *
     * @param userName
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        SysUser queryObj = new SysUser();
        queryObj.setUsername(userName);
        SysUser currentUser = sysUserService.getOne(Wrappers.query(queryObj));
        return getUser(currentUser);
    }

    /**
     * 社交账号登陆
     *
     * @param code
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserBySocial(String code) throws UsernameNotFoundException {
        log.info("手机号为code -> {}", code);
        SysUser queryObj = new SysUser();
        queryObj.setPhone(code);
        SysUser user = sysUserService.getOne(Wrappers.query(queryObj));
        return getUser(user);
    }

    /**
     * 获取权限列表
     * @param currentUser
     * @return
     */
    private UserDetails getUser(SysUser currentUser) {
        if (currentUser == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        Set<String> authSet = new HashSet<>();
        authSet.add(CommonConstants.BASE_ROLE);
        List<SysRole> roleList = sysRoleService.findRolesByUserId(currentUser.getUserId());
        List<String> permissions = sysUserService.findPermissionsByUserId(currentUser.getUserId());


        Set<String> noneRepeatPermission = permissions.stream().filter(StrUtil::isNotBlank).collect(Collectors.toSet());
        noneRepeatPermission.forEach(p -> {
            authSet.addAll(Arrays.stream(p.split(StrUtil.COMMA)).filter(StrUtil::isNotBlank).collect(Collectors.toSet()));
        });
        authSet.addAll(roleList.stream().map(sysRole -> CommonConstants.ROLE + sysRole.getRoleCode().toUpperCase()).collect(Collectors.toSet()));
        Collection<? extends GrantedAuthority> authorities
                = AuthorityUtils.createAuthorityList(authSet.toArray(new String[0]));
        return new UserDetail(currentUser.getUserId(), currentUser.getTenantId(), currentUser.getDeptId(), currentUser.getUsername(), SecurityConstants.BCRYPT + currentUser.getPassword(), roleList, permissions, authorities);
    }

}
